﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Workflow.Silverlight.Controls;
using System.Diagnostics;

namespace WorkflowDesigner.Workflow.Item
{
    public partial class FlowBeeline : WorkflowBase
    {
        // 箭头
        protected ArrowLine m_lineArrow = null;

        protected Color m_clrLineNormal = Colors.Black;
        protected Color m_clrLineFocus = Colors.Blue;
        protected double m_dLineWidth = 3.0;

        protected WorkflowBase m_nodeStart = null;
        protected WorkflowBase m_nodeEnd = null;

        public FlowBeeline()
        {
            InitializeComponent();
            OnInit();
        }

        protected override void OnInit()
        {
            base.OnInit();

            m_lineArrow = new ArrowLine();
            this.LayoutRoot.Children.Add(m_lineArrow);
            // 绘制形状的轮廓
            m_lineArrow.Opacity = 0.9;
            m_lineArrow.Background = new SolidColorBrush(m_clrLineNormal);
            // 形状轮廓的粗细
            m_lineArrow.StrokeThickness = m_dLineWidth;
            m_lineArrow.ArrowSize = new Size(3, 10);

            // 起始处的小圈圈
            circleStart.Fill = new SolidColorBrush(m_clrLineNormal);
            circleStart.Stroke = new SolidColorBrush(m_clrLineNormal);

            m_lineArrow.SetValue(Canvas.ZIndexProperty, 2);
            circleStart.SetValue(Canvas.ZIndexProperty, 3);
        }

        public override bool IsFocus
        {
            get
            {
                return m_isFocus;
            }
            set
            {
                m_isFocus = value;
                if (!this.IsDeleted)
                {
                    if (m_isFocus)
                    {
                        // 焦点状态
                        m_lineArrow.Background = new SolidColorBrush(m_clrLineFocus);
                        circleStart.Fill = new SolidColorBrush(m_clrLineFocus);
                        circleStart.Stroke = new SolidColorBrush(m_clrLineFocus);
                        App.theMainView.SetFlowItemFocus(this);
                        this.SetValue(Canvas.ZIndexProperty, App.NextMaxIndex);
                    }
                    else
                    {
                        m_lineArrow.Background = new SolidColorBrush(m_clrLineNormal);
                        circleStart.Fill = new SolidColorBrush(m_clrLineNormal);
                        circleStart.Stroke = new SolidColorBrush(m_clrLineNormal);
                        this.SetValue(Canvas.ZIndexProperty, App.NextMaxIndex);
                    }
                }
            }
        }

        public WorkflowBase StartNode
        {
            get
            {
                return this.m_nodeStart;
            }
        }

        public WorkflowBase EndNode
        {
            get
            {
                return this.m_nodeEnd;
            }
        }

        public override FlowItemType ItemType
        {
            get
            {
                return FlowItemType.Beeline;
            }
        }

        public bool InitLine(WorkflowBase objStartNode, WorkflowBase objEndNode)
        {
            if((objStartNode == null)
                || (objEndNode == null)
                || (objStartNode.ItemType == FlowItemType.End)
                || (objStartNode.ItemType == FlowItemType.Beeline)
                || (objStartNode.ItemType == FlowItemType.Unknown)
                || (objEndNode.ItemType == FlowItemType.Beeline)
                || (objEndNode.ItemType == FlowItemType.Unknown)
                || (objEndNode.ItemType == FlowItemType.Start)
                )
            {
                if ((objEndNode == null) && (objEndNode.ItemType == FlowItemType.Start))
                {
                    MessageBox.Show("起始节点不能有前驱事件", "警告", MessageBoxButton.OK);
                }
                return false;
            }

            Point ptCenterStart = objStartNode.CenterPoint;
            Point ptCenterEnd = objEndNode.CenterPoint;

            // 以下计算都基于控件坐标系来计算

            // 把 ptCenterEnd 从全局坐标转化为 objStartNode 的控件坐标
            ptCenterEnd.X = ptCenterEnd.X - objStartNode.Location.X;
            ptCenterEnd.Y = ptCenterEnd.Y - objStartNode.Location.Y;
            Point ptStart = objStartNode.GetCrossPoint(ptCenterEnd);
            // 把 ptCenterStart 从全局坐标转化为 objEndNode 的控件坐标
            ptCenterStart.X = ptCenterStart.X - objEndNode.Location.X;
            ptCenterStart.Y = ptCenterStart.Y - objEndNode.Location.Y;
            Point ptEnd = objEndNode.GetCrossPoint(ptCenterStart);

            // ptStart 属于控件坐标，需要转化为全局坐标，所以需要加上控件偏移量
            ptStart.X = ptStart.X + objStartNode.Location.X;
            ptStart.Y = ptStart.Y + objStartNode.Location.Y;
            // ptEnd 属于控件坐标，需要转化为全局坐标，所以需要加上控件偏移量
            ptEnd.X = ptEnd.X + objEndNode.Location.X;
            ptEnd.Y = ptEnd.Y + objEndNode.Location.Y;

            m_lineArrow.StartPoint = ptStart;
            m_lineArrow.EndPoint = ptEnd;

            circleStart.SetValue(Canvas.TopProperty, ptStart.Y - 3.0);
            circleStart.SetValue(Canvas.LeftProperty, ptStart.X - 3.0);

            this.m_nodeStart = objStartNode;
            this.m_nodeEnd = objEndNode;

            this.BringToTop();

            objStartNode.OnControlMove += new ControlMoveNotify(Notify_OnControlMove);
            objStartNode.OnControlDelete += new ControlDeleteNotify(Notify_OnControlDelete);
            objEndNode.OnControlMove += new ControlMoveNotify(Notify_OnControlMove);
            objEndNode.OnControlDelete += new ControlDeleteNotify(Notify_OnControlDelete);

            return true;
        }

        /// <summary>
        /// 监听线条两端的节点，如果他们移动则线条可能也要变化
        /// </summary>
        /// <param name="node"></param>
        void Notify_OnControlDelete(WorkflowBase node)
        {
            if (this.IsDeleted)
            {
                return;
            }
            if (node == m_nodeStart)
            {
                m_nodeStart.OnControlMove -= new ControlMoveNotify(Notify_OnControlMove);
                m_nodeStart.OnControlDelete -= new ControlDeleteNotify(Notify_OnControlDelete);
                m_nodeEnd.OnControlMove -= new ControlMoveNotify(Notify_OnControlMove);
                m_nodeEnd.OnControlDelete -= new ControlDeleteNotify(Notify_OnControlDelete);
                m_nodeStart = null;
                this.OnDelete();
            }
            else if (node == m_nodeEnd)
            {
                if ((m_nodeStart != null)
                    && ((m_nodeStart.IsDeleted) || (m_nodeStart.ItemType != FlowItemType.Condition)))
                {
                    m_nodeStart.OnControlMove -= new ControlMoveNotify(Notify_OnControlMove);
                    m_nodeStart.OnControlDelete -= new ControlDeleteNotify(Notify_OnControlDelete);
                    m_nodeStart = null;
                    m_nodeEnd.OnControlMove -= new ControlMoveNotify(Notify_OnControlMove);
                    m_nodeEnd.OnControlDelete -= new ControlDeleteNotify(Notify_OnControlDelete);
                    m_nodeEnd = null;
                    this.OnDelete();
                }
                else if ((m_nodeStart == null) || (m_nodeStart.IsDeleted))
                {
                    m_nodeStart.OnControlMove -= new ControlMoveNotify(Notify_OnControlMove);
                    m_nodeStart.OnControlDelete -= new ControlDeleteNotify(Notify_OnControlDelete);
                    m_nodeStart = null;
                    m_nodeEnd.OnControlMove -= new ControlMoveNotify(Notify_OnControlMove);
                    m_nodeEnd.OnControlDelete -= new ControlDeleteNotify(Notify_OnControlDelete);
                    m_nodeEnd = null;
                    this.OnDelete();
                }
                else
                {
                    m_nodeEnd.OnControlMove -= new ControlMoveNotify(Notify_OnControlMove);
                    m_nodeEnd.OnControlDelete -= new ControlDeleteNotify(Notify_OnControlDelete);
                    m_nodeEnd = null;
                }
            }
        }

        /// <summary>
        /// 监听线条两端的节点，如果他们移动则线条也要移动
        /// </summary>
        /// <param name="node"></param>
        void Notify_OnControlMove(WorkflowBase node)
        {
            if (this.IsDeleted)
            {
                return;
            }
            if ((node == m_nodeStart) || (node == m_nodeEnd))
            {
                Point ptCenterStart = m_nodeStart.CenterPoint;
                Point ptCenterEnd = m_nodeEnd.CenterPoint;

                // 把 ptCenterEnd 从全局坐标转化为 objStartNode 的控件坐标
                ptCenterEnd.X = ptCenterEnd.X - m_nodeStart.Location.X;
                ptCenterEnd.Y = ptCenterEnd.Y - m_nodeStart.Location.Y;
                Point ptStart = m_nodeStart.GetCrossPoint(ptCenterEnd);
                // 把 ptCenterStart 从全局坐标转化为 objEndNode 的控件坐标
                ptCenterStart.X = ptCenterStart.X - m_nodeEnd.Location.X;
                ptCenterStart.Y = ptCenterStart.Y - m_nodeEnd.Location.Y;
                Point ptEnd = m_nodeEnd.GetCrossPoint(ptCenterStart);

                // ptStart 属于控件坐标，需要转化为全局坐标，所以需要加上控件偏移量
                ptStart.X = ptStart.X + m_nodeStart.Location.X;
                ptStart.Y = ptStart.Y + m_nodeStart.Location.Y;
                // ptEnd 属于控件坐标，需要转化为全局坐标，所以需要加上控件偏移量
                ptEnd.X = ptEnd.X + m_nodeEnd.Location.X;
                ptEnd.Y = ptEnd.Y + m_nodeEnd.Location.Y;

                m_lineArrow.StartPoint = ptStart;
                m_lineArrow.EndPoint = ptEnd;

                circleStart.SetValue(Canvas.TopProperty, ptStart.Y - 3.0);
                circleStart.SetValue(Canvas.LeftProperty, ptStart.X - 3.0);

                this.BringToTop();
            }
        }
    }
}
